/* 迭代器模式 */

pub trait Iterator<T> {
    fn next(&mut self) -> &T;

    fn is_done(&self) -> bool;
}

pub trait Aggregate<T> {
    fn create_iterator(&self) -> Box<dyn Iterator<T> + '_>;
}

pub struct Array<T> {
    values: Vec<T>
}

impl <T> Array<T> {
    pub fn new() -> Array<T> {
        Array {
            values: Vec::new()
        }
    }

    pub fn push(&mut self, t: T) {
        self.values.push(t);
    }
}

impl <T> Aggregate<T> for Array<T> {
    fn create_iterator(&self) -> Box<dyn Iterator<T> + '_> {
        Box::new(ArrayIterator::new(self))
    }
}

struct ArrayIterator<'a, T> {
    array: &'a Array<T>,
    index: usize
}

impl <'a, T> ArrayIterator<'a, T> {
    fn new(array: &'a Array<T>) -> ArrayIterator<'a, T> {
        ArrayIterator{
            array: array,
            index: 0
        }
    }
}

impl <'a, T> Iterator<T> for ArrayIterator<'a, T> {
    fn next(&mut self) -> &T {
        self.index = self.index + 1;
        &self.array.values[self.index - 1]
    }

    fn is_done(&self) -> bool {
        self.index == self.array.values.len()
    }
}

pub struct Food {
    pub name: String
}



#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_iterator_1() {
        let mut array = Array::new();
        array.push(Food{name: String::from("面包")});
        array.push(Food{name: String::from("香肠")});
        array.push(Food{name: String::from("沙拉")});
        array.push(Food{name: String::from("牛排")});

        let mut itr = array.create_iterator();

        while !itr.is_done() {
            let food = itr.next();
            println!("{}", food.name);
        }
    }
}